﻿using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using System.Security.Claims;
using ZGLXM.Domain;

namespace ZGLXM.Read.Api.Interceptor
{
    public class AuditTrailInterceptor : SaveChangesInterceptor
    {
        private readonly IHttpContextAccessor _httpContextAccessor;

        public AuditTrailInterceptor(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        public override InterceptionResult<int> SavingChanges(DbContextEventData Data, InterceptionResult<int> result)
        {
            TrackChanges(Data);
            return base.SavingChanges(Data, result);
        }

        public override ValueTask<InterceptionResult<int>> SavingChangesAsync(DbContextEventData Data, InterceptionResult<int> result, CancellationToken cancellationToken = default)
        {
            TrackChanges(Data);
            return base.SavingChangesAsync(Data, result, cancellationToken);
        }

        private void TrackChanges(DbContextEventData data)
        {
            ArgumentNullException.ThrowIfNull(data.Context);
            data.Context.ChangeTracker.DetectChanges();

            foreach (var entry in data.Context.ChangeTracker.Entries())
            {
                //遍历所有要操作的实体
                if (entry.Entity is IAuditable auditable)
                {
                    switch (entry.State)
                    {
                        case EntityState.Added:
                            UpdateAuditFields(auditable, "Add");
                            break;
                        case EntityState.Modified:
                            UpdateAuditFields(auditable, "Update");
                            break;
                        case EntityState.Deleted:
                            UpdateAuditFields(auditable, "Delete");
                            entry.State = EntityState.Modified;
                            break;
                    }
                }
            }
        }

        public void UpdateAuditFields(IAuditable auditable, string action)
        {
            var currentTime = DateTime.Now;
            //const int adminId = 1; //TODO: 这里需要从httpContext中获取当前登录的用户Id
            //const string adminName = "admin"; //TODO: 这里需要从httpContext中获取当前登录的用户名

            int adminId = Convert.ToInt32(_httpContextAccessor.HttpContext?.User.FindFirstValue("Jti"));
            string adminName = _httpContextAccessor.HttpContext?.User.FindFirstValue("Sub")!;

            switch (action)
            {
                case "Add":
                    auditable.CreateOperatorId = adminId;
                    auditable.CreateOperatorName = adminName;
                    auditable.CreateTime = currentTime;
                    break;
                case "Update":
                    auditable.ModeifyOperatorId = adminId;
                    auditable.ModifyOperatorName = adminName;
                    auditable.ModifyTime = currentTime;
                    break;
                case "Delete":
                    auditable.DeleteOperatorId = adminId;
                    auditable.DeleteOperatorName = adminName;
                    auditable.DeleteTime = currentTime;
                    break;
            }
        }
    }
}
